<?php


namespace app\api\controller;
use hg\apidoc\annotation as Apidoc;
use think\facade\Db;

/**
 * @Apidoc\Title("抽卡模块 ")
 */
class Card extends ApiBase
{
    private $draw_num       = 1; // 用户初始抽奖次数
    private $share_draw_num = 1; // 用户可分享次数(分享获得1次抽奖机会, 不可分享改为0)

    /**
     * 获取用户分享次数
     * @param $user_id
     * @return float|int|string
     * date 2021/4/4 18:37
     */
    private function get_share_num($user_id) {
        $share_num = 0;
        if($this->share_draw_num > 0) {
            $share_num = Db::name('card_share')->where([
                'user_id'   => $user_id,
                'log_date'  => date('Y-m-d')
            ])->count();
        }
        return $share_num;
    }

    /**
     * 获取用户抽奖次数
     * @param $user_id
     * @return float|int|string
     * date 2021/4/4 18:37
     */
    private function get_draw_num($user_id) {
        return Db::name('card_log')->where([
            'user_id'   => $user_id,
            'log_date'  => date('Y-m-d')
        ])->count();
    }

    /**
     * @Apidoc\Title("用户抽卡信息")
     * @Apidoc\Url("/api/card_index")
     * @Apidoc\Method("GET")
     * @Apidoc\Returned("draw_num", type="int", desc="抽卡总次数")
     * @Apidoc\Returned("have_num", type="int", desc="剩余抽奖次数")
     * @Apidoc\Returned("share_num", type="int", desc="已分享次数")
     * @Apidoc\Returned("is_complete", type="int", desc="是否已集齐 true 已集齐 false未集齐")
     * @Apidoc\Returned("have_share_num", type="int", desc="剩余分享次数剩余分享次数")
     * @Apidoc\Returned("card_detail", type="list", desc="已获取卡片详情",
     *              @Apidoc\Returned("card_id", type="int", desc="卡片id"),
     *              @Apidoc\Returned("name", type="string", desc="卡片名称"),
     *              @Apidoc\Returned("image", type="string", desc="图片"),
     *              @Apidoc\Returned("number", type="int", desc="已拥有数量"),
     *  )
     *
     */
    public function index() {
        try {
            $user_id = $this->get_user_id();
            // 初始抽奖次数
            $draw_num = $this->draw_num;
            // 分享次数
            $share_num = $this->get_share_num($user_id);
            // 用户已抽奖次数
            $user_draw_num = $this->get_draw_num($user_id);
            $card_list   = Db::name('card')->field('id as card_id,name,image')->select()->toArray(); //卡片全部
            foreach ($card_list as $key => &$value) {
                $value['number'] = Db::name('card_log')->where('user_id',$user_id)->where('card_id',$value['card_id'])->count();
            }
            $card_list_ids = \array_column($card_list,'card_id');
            $user_card_id  = Db::name('card_log')->where('user_id',$user_id)->group('card_id')->column('id');


            json_response(1, 'success', [
                'draw_num'          => $draw_num + $share_num, // 抽奖总次数
                'have_num'          => $draw_num + $share_num - $user_draw_num, // 剩余抽奖次数
                'share_num'         => $share_num, // 已分享次数
                'have_share_num'    => $this->share_draw_num - $share_num, // 剩余分享次数
                'card_detail'       => $card_list,
                'is_complete'       => count($user_card_id) >= count($card_list_ids)
            ]);
        } catch (\Exception $e) {
            json_response(0, '接口错误', [
                'info' => $e->getMessage(),
                'line' => $e->getLine()
            ]);
        }
    }

 
    /**
     * @Apidoc\Title("抽卡")
     * @Apidoc\Url("/api/card_draw")
     * @Apidoc\Method("POST")
     * @Apidoc\Returned("card_id", type="int", desc="卡片id")
     * @Apidoc\Returned("card_type", type="int", desc="卡片类型 1普通 2特殊")
     * @Apidoc\Returned("card_name", type="int", desc="卡片名称")
     * @Apidoc\Returned("card_image", type="string", desc="卡片图片")
     */
    public function draw() {
        try {
            $user_id = $this->get_user_id();
            redis_lock("{$this->redis_key}:draw:{$user_id}", $user_id, function($user_id, $redis) {
                // 初始抽奖次数
                $draw_num = $this->draw_num;
                // 分享次数
                $share_num = $this->get_share_num($user_id);
                // 用户已抽奖次数
                $user_draw_num = $this->get_draw_num($user_id);
                if($user_draw_num >= $draw_num + $share_num) {
                    return error('抽奖次数不足');
                }

                // 获取卡片列表
                $card_list = redis_get("{$this->redis_key}:draw_cardList", function() {
                    return Db::name('card')->where('status', 1)->order('ratio ASC')->field('id as card_id, type, name, image, stock, day_stock, win_times, ratio')->select()->toArray();
                }, 5);
                if(empty($card_list)) return error('活动未开放, 请稍后再试~');


                // 判断卡片库存以及其他逻辑
                $date = date('Y-m-d');
                foreach($card_list as $key=>$item) {
                    // 普通卡不判断库存
                    if($item['type'] == 1) {
                        continue;
                    }

                    // 判断卡片总库存
                    if($item['stock'] > 0) {
                        // 判断卡片库存
                        $stock = $redis->lLen("{$this->redis_key}:CardStock:{$item['card_id']}");
                        // 总库存不足, 从抽奖列表移除
                        if(empty($stock)) {
                            unset($card_list[$key]); continue;
                        }
                    }

                    // 判断卡片每日库存
                    if($item['day_stock'] > 0) {
                        $today_send = $redis->get("{$this->redis_key}:CardSendLog:{$item['card_id']}_{$date}");
                        if($today_send >= $item['day_stock']) {
                            unset($card_list[$key]); continue;
                        }
                        // 数据库再验证一次
                        $today_send2 = Db::name('card_log')->where(['card_id'=>$item['card_id'], 'log_date'=>$date])->count();
                        if($today_send2 >= $item['day_stock']) {
                            unset($card_list[$key]); continue;
                        }
                    }

                    // 判断奖品用户抽中次数
                    if($item['win_times'] > 0) {
                        $user_send = Db::name('card_log')->where(['user_id'=>$user_id, 'card_id'=>$item['card_id']])->count();
                        if(!empty($user_send)) {
                            unset($card_list[$key]); continue;
                        }
                    }
                }
                if(!count($card_list))  return error('无库存');
                $card = draw($card_list, 'ratio');
                // redis队列减库存
                if($card['stock'] > 0) {
                    $res = $redis->rPop("{$this->redis_key}:CardStock:{$card['card_id']}");
                    // 减库存失败, 发放无价值卡片
                    if(empty($res)) {
                        return error('当前访问人数过多, 请稍后再试~');
                    }
                }
                // 奖品入库
                Db::name('card_log')->insertGetId([
                    'user_id'       => $user_id,
                    'card_id'       => $card['card_id'],
                    'card_type'     => $card['type'],
                    'card_name'     => $card['name'],
                    'card_image'    => $card['image'],
                    'status'        => 0,
                    'log_time'      => time(),
                    'log_date'      => $date
                ]);
                // 中奖记录存储
                if($card['day_stock'] > 0) {
                    $redis_day_stock_key = "{$this->redis_key}:CardSendLog:{$card['card_id']}_{$date}";
                    $redis->incr($redis_day_stock_key);
                    $redis->expire($redis_day_stock_key, 86400);
                }
                return success('抽卡成功', [
                    'card_id'       => $card['card_id'],
                    'card_type'     => $card['type'],
                    'card_name'     => $card['name'],
                    'card_image'    => $card['image']
                ]);
            });
        } catch (\Exception $e) {
            json_response(0, '接口错误', [
                'info' => $e->getMessage(),
                'line' => $e->getLine()
            ]);
        }
    }

 
    /**
     * @Apidoc\Title("分享卡片")
     * @Apidoc\Url("/api/card_share_log")
     * @Apidoc\Method("GET")
     */
    public function share_log() {
        try {
            $user_id = $this->get_user_id();
            // 判断是否开启分享
            if(empty($this->share_draw_num)) {
                return error('分享未开启');
            }
            redis_lock("{$this->redis_key}:share_log:{$user_id}", $user_id, function($user_id) {
                // 判断分享次数
                $user_share_num = Db::name('card_share')->where([
                    'user_id'   => $user_id,
                    'log_date'  => date('Y-m-d')
                ])->count();
                if($user_share_num >= $this->share_draw_num) {
                    return error('今日已分享');
                }
                $res = Db::name('card_share')->insert([
                    'user_id'   => $user_id,
                    'log_time'  => time(),
                    'log_date'  => date('Y-m-d')
                ]);
                if($res) {
                    return success('分享成功');
                }else {
                    return error('分享失败');
                }
            }, 3);
        } catch (\Exception $e) {
            json_response(0, '接口错误', [
                'info' => $e->getMessage(),
                'line' => $e->getLine()
            ]);
        }
    }

}